import Phaser from 'phaser';
import generateSprites from '../utils/sprites';

export default class GameScene extends Phaser.Scene {
  private player!: Phaser.Physics.Arcade.Sprite;
  private cursors!: Phaser.Types.Input.Keyboard.CursorKeys;
  private wasd!: any;
  private speed: number = 220;
  private worldW: number = 2000;
  private worldH: number = 1400;

  constructor() {
    super({ key: 'GameScene' });
  }

  preload(): void {
    // Minimal skeleton: no external assets required.
  }

  create(): void {
    // world bounds & camera
    this.physics.world.setBounds(0, 0, this.worldW, this.worldH);
    this.cameras.main.setBounds(0, 0, this.worldW, this.worldH);

    // background + soft grid for visual reference
    const g = this.add.graphics({ x: 0, y: 0 });
    g.fillStyle(0x071028, 1);
    g.fillRect(0, 0, this.worldW, this.worldH);

    g.lineStyle(1, 0xffffff, 0.06);
    const step = 48;
    for (let x = 0; x < this.worldW; x += step) {
      g.moveTo(x, 0);
      g.lineTo(x, this.worldH);
    }
    for (let y = 0; y < this.worldH; y += step) {
      g.moveTo(0, y);
      g.lineTo(this.worldW, y);
    }
    g.strokePath();

    // generate and register procedural sprites as Phaser textures
    const sprites = generateSprites(this);
    // create player using one of the generated idle frames
    const playerFrameKey = sprites.player.frames.idle[0];
    this.player = this.physics.add.sprite(this.worldW / 2, this.worldH / 2, playerFrameKey);
    const pSize = sprites.player.baseSize * sprites.player.scale;
    this.player.setDisplaySize(pSize, pSize);
    this.player.setCollideWorldBounds(true);
    this.player.setOrigin(0.5, 0.5);
    const body = this.player.body as Phaser.Physics.Arcade.Body | null;
    if (body) body.setSize(12 * sprites.player.scale, 12 * sprites.player.scale);

    // controls: arrow keys + WASD
    this.cursors = this.input.keyboard!.createCursorKeys();
    this.wasd = this.input.keyboard!.addKeys('W,S,A,D') as any;

    // camera follow
    this.cameras.main.startFollow(this.player, true, 0.12, 0.12);
    this.cameras.main.setZoom(1);

    // simple HUD (fixed to camera)
    const hud = this.add.text(16, 16, 'WASD / Arrows to move — Click to dash — P to save pos', {
      fontSize: '16px',
      color: '#ffffff'
    });
    hud.setScrollFactor(0);

    // pointer interaction: dash toward clicked point
    this.input.on('pointerdown', (pointer: Phaser.Input.Pointer) => {
      const wp = this.cameras.main.getWorldPoint(pointer.x, pointer.y);
      this.physics.moveTo(this.player, wp.x, wp.y, 520);
      this.time.delayedCall(220, () => {
        this.player.setVelocity(0, 0);
      });
    });

    // restore saved player position (if any)
    try {
      const raw = window.localStorage.getItem('phaser-player-pos');
      if (raw) {
        const p = JSON.parse(raw);
        if (p && typeof p.x === 'number' && typeof p.y === 'number') {
          this.player.setPosition(p.x, p.y);
          this.cameras.main.centerOn(p.x, p.y);
        }
      }
    } catch (e) {
      // ignore
    }

    // save position with P
    const saveKey = this.input.keyboard!.addKey(Phaser.Input.Keyboard.KeyCodes.P);
    saveKey.on('down', () => {
      window.localStorage.setItem('phaser-player-pos', JSON.stringify({ x: this.player.x, y: this.player.y }));
      const t = this.add.text(16, 40, 'Saved position', { fontSize: '14px', color: '#a78bfa' }).setScrollFactor(0);
      this.time.delayedCall(1100, () => t.destroy());
    });

    // spawn a few simple moving "enemies" (reusing the small texture)
    const enemies = this.physics.add.group();
    for (let i = 0; i < 8; i++) {
      const texture = Math.random() < 0.6 ? sprites.enemy.slime : sprites.enemy.bat;
      const e = this.physics.add.sprite(
        Phaser.Math.Between(80, this.worldW - 80),
        Phaser.Math.Between(80, this.worldH - 80),
        texture
      );
      const eSize = sprites.player.baseSize * sprites.player.scale;
      e.setDisplaySize(eSize, eSize);
      e.setTint(Phaser.Display.Color.RandomRGB().color);
      e.setCollideWorldBounds(true);
      const eb = e.body as Phaser.Physics.Arcade.Body | null;
      if (eb) eb.setVelocity(Phaser.Math.Between(-60, 60), Phaser.Math.Between(-60, 60));
      e.setBounce(1);
      enemies.add(e);
    }

    // simple overlap effect
    this.physics.add.overlap(this.player, enemies, (_p, en) => {
      (en as Phaser.GameObjects.Sprite).setTintFill(0xff6b6b);
      this.time.delayedCall(120, () => {
        (en as Phaser.GameObjects.Sprite).clearTint();
      });
    });
  }

  update(_time: number, delta: number): void {
    const dt = delta / 1000;
    let vx = 0;
    let vy = 0;

    if (this.cursors.left?.isDown || this.wasd?.A?.isDown) vx -= 1;
    if (this.cursors.right?.isDown || this.wasd?.D?.isDown) vx += 1;
    if (this.cursors.up?.isDown || this.wasd?.W?.isDown) vy -= 1;
    if (this.cursors.down?.isDown || this.wasd?.S?.isDown) vy += 1;

    const len = Math.hypot(vx, vy) || 1;
    const pbody = this.player.body as Phaser.Physics.Arcade.Body | null;
    if (pbody) {
      pbody.setVelocity((vx / len) * this.speed, (vy / len) * this.speed);
    }
  }
}
